package yuyue.note01;

import org.aopalliance.intercept.MethodInterceptor;
import org.junit.Test;
import yuyue.note01.entity.Person;
import yuyue.note01.entity.Swimmable;

import java.util.*;
import java.util.function.*;

/**
 * lambda相关示例
 */
public class Note01Test {
    @Test
    //匿名内部类启动新的线程
    //匿名内部类中重点就是重写方法，lambda简化其写法
    public void fun1() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getId() + ":新线程任务执行！");
            }
        }).start();

        System.out.println(Thread.currentThread().getId() + ":主线程");
    }

    @Test
    //lambda写法
    public void fun2() {
        new Thread(
                // lambda表达式
                () -> System.out.println(Thread.currentThread().getId() + ":新线程任务执行！")
        ).start();

        System.out.println(Thread.currentThread().getId() + ":主线程");
    }

    @Test
    //lambda无参练习
    public void fun3() {
        goSwimming(() -> {
            System.out.println("游泳中！");
        });
    }

    public static void main(String[] args) {
        goSwimming(() -> {
            System.out.println("游泳中！");
        });
    }

    private static void goSwimming(Swimmable swimmable) {
        swimmable.swimming();
    }

    @Test
    //lambda有参有返回值练习
    public void fun4() {
        ArrayList<Person> arrayList = new ArrayList<>();
        arrayList.add(new Person("胡歌", 28, 188));
        arrayList.add(new Person("姚明", 28, 191));
        arrayList.add(new Person("刘亦菲", 28, 170));
        arrayList.add(new Person("风清扬", 28, 166));
        arrayList.add(new Person("大象", 28, 260));

        //以身高排序
        Collections.sort(arrayList, (Person p1, Person p2) -> {
            return p1.getHeight() - p2.getHeight();
        });

        for (Person person :
                arrayList) {
            System.out.println(person);
        }
    }

    @Test
    //以匿名内部类实现无参练习
    public void fun5() {
        goSwimming(new Swimmable() {
            @Override
            public void swimming() {
                System.out.println("匿名内部类游泳中！");
            }
        });
    }

    @Test
    //生产者函数式接口Supplier示例，打印最大值
    public void fun6() {
        printMax(() -> {
            //获取最大值
            int[] arr = {10, 20, 1000, 300, 6};
            Arrays.sort(arr);
            return arr[arr.length - 1];
        });
    }

    private void printMax(Supplier<Integer> supplier) {
        //执行函数式接口方法
        Integer max = supplier.get();
        System.out.println(max);
    }

    @Test
    //消费者函数式接口Consumer示例，打印大小写
    //消费者泛型相同时，可以使用默认方法andThen实现组合消费
    public void fun8(){
        //定义不同的消费方式：大写、小写
        printUL((String s) -> {System.out.println(s.toUpperCase());},
                (String s) -> {System.out.println(s.toLowerCase());});
    }

    private void printUL(Consumer<String> c1, Consumer<String> c2) {
        String str = "test";

        //单次消费示例
        c1.accept(str);

        //组合消费示例
        c1.andThen(c2).accept(str);
    }

    @Test
    //转换函数式接口示例
    public void fun9(){
        //定义不同的转换
        printFun((String str) -> {return Integer.parseInt(str);},
                (Integer i) -> {return i * 10;});
    }

    private void printFun(Function<String, Integer> f1, Function<Integer, Integer> f2) {
        String str = "5";

        //组合转换
        Integer i = f1.andThen(f2).apply(str);

        System.out.println(i);
    }

    @Test
    //判断函数式接口示例
    public void fun10(){
        printPredicate(s -> s.contains("H"),
                       s -> s.contains("W"));
    }

    private void printPredicate(Predicate<String> h, Predicate<String> w) {
        String str = "Huawei";

        System.out.println(h.test(str));//单项判断
        System.out.println(h.and(w).test(str));//组合判断与
        System.out.println(h.or(w).test(str));//组合判断或
        System.out.println(h.negate().test(str));//组合判断非
    }

    @Test
    //对象::方法名
    public void fun11(){
        Date now = new Date();

        //lambda 非引用
        Supplier<Long> supp = () -> now.getTime();
        System.out.println(supp.get());

        //引用方式实现
        Supplier<Long> supp2 = now::getTime;
        System.out.println(supp2.get());
    }

    @Test
    //类名::静态方法
    public void fun12(){
        //lambda 非引用
        Supplier<Long> supplier = () -> System.currentTimeMillis();
        System.out.println(supplier.get());

        //引用方式实现
        Supplier<Long> supplier2 = System::currentTimeMillis;
        System.out.println(supplier2.get());
    }

    @Test
    //类名::普通方法
    public void fun13(){
        //lambda 非引用
        Function<String, Integer> f1 = (s) -> s.length();
        System.out.println(f1.apply("abc"));

        //引用方式实现
        Function<String, Integer> f2 = String::length;
        System.out.println(f2.apply("abc"));
    }

    @Test
    //类名::new 调用的构造器
    public void fun14(){
        //lambda 非引用
        Supplier<Person> s1 = () -> new Person("胡歌", 18, 180);
        System.out.println(s1.get());

        //引用方式实现，无参构造，没有合适的函数式接口使用3个参数的构造器
        Supplier<Person> s2 = Person::new;
        System.out.println(s2.get());
    }
    
    @Test
    //调用数组的构造器
    public void fun15(){
        //lambda 非引用
        Function<Integer, String[]> f1 = (length) -> new String[length];
        System.out.println(f1.apply(5).length);

        //引用方式实现
        Function<Integer, String[]> f2 = String[]::new;
        System.out.println(f2.apply(5).length);
    }

    @Test
    //比较
    public void fun16(){
        Comparator<Integer> comparator = (o1, o2) -> o1 - o2;
        System.out.println(comparator.compare(5, 8));
    }
}
